/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_ssap_server_hdi.h"
#include "sle_ssap_config.h"
#include "sle_ssap_server_config.h"
#include "sle_hal_errcode.h"
#include "sle_hilog.h"
#include "sle_ssap_server.h"
#include "sle_callback_adapter.h"

uint32_t g_hasSendPack = 0;
uint32_t NEED_GIVE_DOG_FOOD = 1000;
uint32_t SEND_TIMES_FOR_DOG = 40000;
SleHdiErrorCode SleHdiAdapterSsapsRegisterServer(const SleUuid *appUuid, uint8_t *serverId)
{
    SLE_ASSERT_AND_RETURN_RET(appUuid != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(serverId != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_register_server((sle_uuid_t*)appUuid, serverId);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsUnregisterServer(uint8_t serverId)
{
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_unregister_server(serverId);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsAddService(uint8_t serverId, const SleUuid *ServiceUuid, bool IsPrimary, uint16_t *handle)
{
    SLE_ASSERT_AND_RETURN_RET(ServiceUuid != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(handle != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_add_service_sync(serverId, (sle_uuid_t*)ServiceUuid, IsPrimary, handle);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsAddProperty(uint8_t serverId, uint16_t serviceHandle, const SsapsPropertyParam *property,
    uint16_t *handle)
{
    SLE_ASSERT_AND_RETURN_RET(property != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(handle != NULL, SLE_HAL_ERR_INVALID_PARAM);
    ssaps_property_info_t property_sdk = {
        .permissions = (uint16_t)property->permissions,
        .operate_indication = (uint32_t)property->opIndication,
        .value_len = property->valueLen,
        .value = property->value,
    };
    memcpy(property_sdk.uuid.uuid, property->uuid.uuid, sizeof(property->uuid.uuid));
    property_sdk.uuid.len = property->uuid.len;
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_add_property_sync(serverId, serviceHandle, &property_sdk, handle);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsAddDescriptor(uint8_t serverId, uint16_t serviceHandle, uint16_t propertyHandle,
    const SsapsDescriptorParam *descriptor, uint16_t *handle)
{
    SLE_ASSERT_AND_RETURN_RET(descriptor != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SLE_ASSERT_AND_RETURN_RET(handle != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ssaps_desc_info_t descriptor_sdk = {
        .permissions = (uint16_t)descriptor->permissions,
        .operate_indication = (uint32_t)descriptor->operateInd,
        .type = (uint8_t)descriptor->type,
        .value_len = descriptor->valueLen,
        .value = descriptor->value,
    };
    memcpy(&(descriptor_sdk.uuid), &(descriptor->uuid), sizeof(sle_uuid_t));
    ret = ssaps_add_descriptor_sync(serverId, serviceHandle, propertyHandle, &descriptor_sdk);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsStartService(uint8_t serverId, uint16_t serviceHandle)
{
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_start_service(serverId, serviceHandle);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsDeleteAllServices(uint8_t serverId)
{
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_delete_all_services(serverId);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsSendResponse(uint8_t serverId, uint16_t connectId, const SsapsSendRspParam *param)
{
    SLE_ASSERT_AND_RETURN_RET(param != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ssaps_send_rsp_t param_sdk = {
        .request_id = param->requestId,
        .status = (uint8_t)param->status,
        .value_len = param->valueLen,
        .value = param->value,
    };
    ret = ssaps_send_response(serverId, connectId, &param_sdk);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsNotifyIndicate(uint8_t serverId, uint16_t connectId, const SsapsNotifyParam *param)
{
    SLE_ASSERT_AND_RETURN_RET(param != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ssaps_ntf_ind_t param_sdk = {
        .handle = param->handle,
        .type = (uint8_t)param->type,
        .value_len = param->valueLen,
        .value = param->value,
    };

    uint8_t data_num = gle_tx_acb_data_num_get();   //获取当前缓冲区大小
    uint32_t watchDog = 0;
    while (data_num == 0) {
        watchDog++;
        if (watchDog % 100 == 0) {
            (void)uapi_watchdog_kick();
        }
        if (watchDog > SEND_TIMES_FOR_DOG) {
            watchDog = 1;
        }
        LOS_TaskYield();
        data_num = gle_tx_acb_data_num_get();
    }
    ret = ssaps_notify_indicate(serverId, connectId, &param_sdk);
    if (ret == 0){
        g_hasSendPack++;
        if (g_hasSendPack >= NEED_GIVE_DOG_FOOD) {
            (void)uapi_watchdog_kick();
            g_hasSendPack = 0;
        }
    }
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsNotifyIndicateByUuid(uint8_t serverId, uint16_t connectId, const SsapsNotyfyByUuidParam *param)
{
    SLE_ASSERT_AND_RETURN_RET(param != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ssaps_ntf_ind_by_uuid_t param_sdk = {
        .start_handle = param->startHandle,
        .end_handle = param->endHandle,
        .type = (uint8_t)param->type,
        .value_len = param->valueLen,
        .value = param->value,
    };
    memcpy(&(param_sdk.uuid), &(param->uuid), sizeof(sle_uuid_t));
    ret = ssaps_notify_indicate_by_uuid(serverId, connectId, &param_sdk);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsSetInfo(uint8_t serverId, const SsapMtuInfo *info)
{
    SLE_ASSERT_AND_RETURN_RET(info != NULL, SLE_HAL_ERR_INVALID_PARAM);
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = ssaps_set_info(serverId, (ssap_exchange_info_t*)info);
    return ret;
}

SleHdiErrorCode SleHdiAdapterSsapsRegisterCallbacks(SleSsapsHdiCallbacks *callbacks)
{
    SLE_ASSERT_AND_RETURN_RET_LOG(callbacks != NULL, SLE_HAL_ERR_INVALID_PARAM, "SleHdiSsapsRegisterCallbacks");
    SleHdiErrorCode ret = SLE_HDI_ERRCODE_FAIL;
    ret = RegisterSsapsCallbackAdapter(callbacks);
    return ret;
}

SleHdiErrorCode GetSleSsapsHdiOpts(SleSsapsHdiOpts *ssapsOpts)
{
    SLE_ASSERT_AND_RETURN_RET_LOG(ssapsOpts != NULL, SLE_HAL_ERR_INVALID_PARAM, "GetSleSsapsHdiOpts");
    ssapsOpts->registerServer = SleHdiAdapterSsapsRegisterServer;
    ssapsOpts->unregisterServer = SleHdiAdapterSsapsUnregisterServer;
    ssapsOpts->addService = SleHdiAdapterSsapsAddService;
    ssapsOpts->addProperty = SleHdiAdapterSsapsAddProperty;
    ssapsOpts->addDescriptor = SleHdiAdapterSsapsAddDescriptor;
    ssapsOpts->startService = SleHdiAdapterSsapsStartService;
    ssapsOpts->deleteAllServices = SleHdiAdapterSsapsDeleteAllServices;
    ssapsOpts->sendResponse = SleHdiAdapterSsapsSendResponse;
    ssapsOpts->sendNotifyIndicate = SleHdiAdapterSsapsNotifyIndicate;
    ssapsOpts->sendNotifyIndicateByUuid = SleHdiAdapterSsapsNotifyIndicateByUuid;
    ssapsOpts->setServerMtuInfo = SleHdiAdapterSsapsSetInfo;
    ssapsOpts->registerServerCbks = SleHdiAdapterSsapsRegisterCallbacks;
    return SLE_HDI_ERRCODE_SUCC;
}